﻿namespace ChoBulkFileProcessor
{
    #region NameSpaces

    using System;
    using System.Text;
    using System.Collections.Generic;
    using Cinchoo.Core.Configuration;
    using System.ComponentModel;
using System.Runtime.Remoting.Contexts;
    using System.Dynamic;
    using Cinchoo.Core.Text.RegularExpressions;
    using System.Text.RegularExpressions;
    using Cinchoo.Core.Diagnostics;
    using Cinchoo.Core;
    using System.Diagnostics;
    using Cinchoo.Core.Xml.Serialization;
    using Cinchoo.Core.IO;
    using System.IO;
    using System.Xml.Serialization;

    #endregion NameSpaces

    [ChoNameValueConfigurationSection("applicationSettings" /*, BindingMode = ChoConfigurationBindingMode.OneWayToSource */, Silent = false)]
    public class ChoAppSettings : ChoConfigurableObject
    {
        internal const string BEGIN_FILE_OPS_TAG = "beginFileOps";
        internal const string MATCH_FILE_OPS_TAG = "matchFileOps";
        internal const string PROCESS_FILE_OPS_TAG = "processFileOps";
        internal const string UNDO_FILE_OPS_TAG = "undoFileOps";
        internal const string SUCCESS_FILE_OPS_TAG = "successFileOps";
        internal const string FAILED_FILE_OPS_TAG = "failedFileOps";

        #region Instance Data Members (Public)

        [ChoPropertyInfo("directories")]
        public string Directories
        {
            get;
            set;
        }

        [ChoPropertyInfo("moveOrCopyToDirectory")]
        public string MoveOrCopyToDirectory
        {
            get;
            set;
        }

        [ChoPropertyInfo("pluginsFolders")]
        public string PlugInsFolders
        {
            get;
            set;
        }

        [ChoPropertyInfo("fileFindMatchingExprData", DefaultValue = @"*.log")]
        public ChoCDATA FileFindMatchingExprData
        {
            get;
            set;
        }

        [ChoIgnoreProperty]
        [XmlIgnore]
        [ChoPropertyDependsOn("FileFindMatchingExprData")]
        public string FileFindMatchingExpr
        {
            get { return FileFindMatchingExprData ?? FileFindMatchingExprData.GetValue(); }
            set { FileFindMatchingExprData = new ChoCDATA(value); }
        }

        [ChoPropertyInfo("fileReplaceMatchingExprData", DefaultValue = @"*.txt")]
        public ChoCDATA FileReplaceMatchingExprData
        {
            get;
            set;
        }

        [ChoIgnoreProperty]
        [XmlIgnore]
        [ChoPropertyDependsOn("FileReplaceMatchingExprData")]
        public string FileReplaceMatchingExpr
        {
            get { return FileReplaceMatchingExprData ?? FileReplaceMatchingExprData.GetValue(); }
            set { FileReplaceMatchingExprData = new ChoCDATA(value); }
        }

        [ChoPropertyInfo("includeSubDir", DefaultValue = "true")]
        public bool IncludeSubDir
        {
            get;
            set;
        }

        [ChoPropertyInfo("resolveCollision", DefaultValue = "true")]
        public bool ResolveCollision
        {
            get;
            set;
        }

        [ChoPropertyInfo("previewMode", DefaultValue = "true")]
        public bool PreviewMode
        {
            get;
            set;
        }

        [ChoPropertyInfo("doCopy", DefaultValue = "true")]
        public bool DoCopy
        {
            get;
            set;
        }

        [ChoPropertyInfo("overwrite", DefaultValue = "true")]
        public bool Overwrite
        {
            get;
            set;
        }

        [ChoPropertyInfo("files", DefaultValue = "true")]
        public bool IsFileProcessEnabled
        {
            get;
            set;
        }

        [ChoPropertyInfo("folders", DefaultValue = "false")]
        public bool IsFolderProcessEnabled
        {
            get;
            set;
        }

        [ChoPropertyInfo("useWildcard", DefaultValue = "true")]
        public bool UseWildcard
        {
            get;
            set;
        }

        [ChoPropertyInfo("createEmptyDir", DefaultValue = "true")]
        public bool CreateEmptyDir
        {
            get { return true; }
            set { }
        }

        private int _maxStatusMsgSize;
        [ChoPropertyInfo("maxStatusMsgSize", DefaultValue = "1000")]
        public int MaxStatusMsgSize
        {
            get { return _maxStatusMsgSize; }
            set
            {
                if (value > 0)
                    _maxStatusMsgSize = value;
            }
        }
        
        [ChoPropertyInfo("plugInsDef")]
        public string PlugInsDef
        {
            get;
            set;
        }

        [ChoPropertyInfo("fileTransTextData")]
        public ChoCDATA FileTransTextData
        {
            get;
            set;
        }

        [ChoIgnoreProperty]
        [XmlIgnore]
        [ChoPropertyDependsOn("FileTransTextData")]
        public string FileTransText
        {
            get { return FileTransTextData != null ? FileTransTextData.GetValue() : null; }
            set { FileTransTextData = new ChoCDATA(value); }
        }

        [ChoPropertyInfo("undoScriptsFolder", DefaultValue = "UndoScripts")]
        public string UndoScriptsFolder;

        #endregion

        public Regex GetFileFindMatchingRegex()
        {
            if (FileFindMatchingExpr.IsNullOrWhiteSpace())
                return null;

            if (UseWildcard)
            {
                string regEx = ChoWildcard.WildcardToRegex(FileFindMatchingExpr);
                return new Regex(regEx /*.Substring(1, regEx.Length - 2)*/, RegexOptions.IgnoreCase | RegexOptions.Compiled);
            }
            else
                return new Regex(FileFindMatchingExpr, RegexOptions.IgnoreCase | RegexOptions.Compiled);
        }

        public string GetPlugInsDefFile()
        {
            string tmpFileName = ChoPath.GetTempFileName();

            File.WriteAllText(tmpFileName, PlugInsDef);

            return tmpFileName;
        }

        public void VerifyPlugInsDef()
        {
            ChoPlugInsDefManager man = new ChoPlugInsDefManager(GetPlugInsDefFile());
            if (!man.ContainsPlugInGroup(BEGIN_FILE_OPS_TAG))
                throw new ApplicationException("Missing '{0}' group".FormatString(BEGIN_FILE_OPS_TAG));
            if (!man.ContainsPlugInGroup(MATCH_FILE_OPS_TAG))
                throw new ApplicationException("Missing '{0}' group".FormatString(MATCH_FILE_OPS_TAG));
            if (!man.ContainsPlugInGroup(PROCESS_FILE_OPS_TAG))
                throw new ApplicationException("Missing '{0}' group".FormatString(PROCESS_FILE_OPS_TAG));
            if (!man.ContainsPlugInGroup(UNDO_FILE_OPS_TAG))
                throw new ApplicationException("Missing '{0}' group".FormatString(UNDO_FILE_OPS_TAG));
            if (!man.ContainsPlugInGroup(SUCCESS_FILE_OPS_TAG))
                throw new ApplicationException("Missing '{0}' group".FormatString(SUCCESS_FILE_OPS_TAG));
            if (!man.ContainsPlugInGroup(FAILED_FILE_OPS_TAG))
                throw new ApplicationException("Missing '{0}' group".FormatString(FAILED_FILE_OPS_TAG));
        }

        public void ResetPlugInsDef()
        {
            PlugInsDef = @"<plugInGroups>
                            <plugIns name=""{0}""></plugIns>
                            <plugIns name=""{1}""></plugIns>
                            <plugIns name=""{2}""></plugIns>
                            <plugIns name=""{3}""></plugIns>
                            <plugIns name=""{4}""></plugIns>
                            <plugIns name=""{5}""></plugIns>
                        </plugInGroups>".FormatString(BEGIN_FILE_OPS_TAG,
                    MATCH_FILE_OPS_TAG, PROCESS_FILE_OPS_TAG, UNDO_FILE_OPS_TAG, SUCCESS_FILE_OPS_TAG, FAILED_FILE_OPS_TAG);
        }

        protected override void OnAfterConfigurationObjectLoaded()
        {
            if (PlugInsDef.IsNullOrWhiteSpace())
            {
                ResetPlugInsDef();
                Persist();
            }

            base.OnAfterConfigurationObjectLoaded();
        }

        public void Reset()
        {
            ChoObject.ResetObject(this);
            ResetPlugInsDef();
            Persist();
        }
    }
}
